package org.flexlancer.canvas
{
	import components.GroupItem;
	import components.Node;
	
	import flash.display.Shape;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.setTimeout;
	
	import mx.containers.Canvas;
	import mx.core.UIComponent;
	import mx.events.DragEvent;
	import mx.managers.DragManager;
	
	import org.flexlancer.Logger.Logger;
	import org.flexlancer.container.NodesContainer;
	import org.flexlancer.managers.SelectionManager;

	public class DataVisualzationCanvas extends Canvas
	{
		private var driverSelection:Shape = new Shape();
		private var mouseDownX:Number = 0;
		private var mouseDownY:Number = 0;
		private var nodes:NodesContainer = new NodesContainer;
		
		public function DataVisualzationCanvas()
		{
			try{
				super();
				
				this.nodes.percentWidth = 100;
				this.nodes.percentHeight = 100;
				this.nodes.x = 0;
				this.nodes.y = 0;
				
				this.addChild(this.nodes);
				this.rawChildren.addChild(this.driverSelection);
				
				this.addEventListener(MouseEvent.MOUSE_DOWN,this.Me_OnMouseDown);
				this.addEventListener(DragEvent.DRAG_ENTER,this.Me_OnDragEnter);
				this.addEventListener(DragEvent.DRAG_DROP,this.Me_OnDragDrop);
			}catch(err:Error){
				Logger.LogE(err);
			}
		}
		
/*
==========================================
==========================================
		GROUP DRAG 'N' DROP SCRIPTS
==========================================
==========================================
*/		
		public function Me_OnMouseDown(evt:MouseEvent):void{
			try{
				this.mouseDownX = this.mouseX;
				this.mouseDownY = this.mouseY;	
				this.addEventListener(MouseEvent.MOUSE_MOVE,this.Me_OnMouseMove);
				this.addEventListener(MouseEvent.MOUSE_UP,this.Me_OnMouseUp);
			}catch(err:Error){
				Logger.LogE(err);
			}
		}
		
		public function Me_OnMouseMove(evt:MouseEvent):void{
			try{
				this.driverSelection.graphics.clear();
				this.driverSelection.graphics.lineStyle( .5, 0x0099FF );
				this.driverSelection.graphics.beginFill( 0x0099FF, 0.2);
				
				var w:int = this.mouseX - this.mouseDownX;
				var h:int = this.mouseY - this.mouseDownY;
				this.driverSelection.graphics.drawRect(this.mouseDownX,this.mouseDownY,w,h);
			}catch(err:Error){
				Logger.LogE(err);
			}
		}
		
		public function Me_OnMouseUp(evt:MouseEvent):void{
			try{
				this.removeEventListener(MouseEvent.MOUSE_UP,this.Me_OnMouseUp);
				this.removeEventListener(MouseEvent.MOUSE_MOVE,this.Me_OnMouseMove);
				
				var arrItems:Array = new Array;
				
				for ( var i:Number = 0 ; i < this.nodes.numChildren ; i ++ ){
					var obj:UIComponent = UIComponent(this.nodes.getChildAt(i));
					if ( this.driverSelection.hitTestObject(obj) ){
						arrItems.push(obj);
					}
				}
				
				SelectionManager.AddSelectionRange(arrItems);
				this.driverSelection.graphics.clear();
			}catch(err:Error){
				Logger.LogE(err);
			}
		}
/*
==========================================
==========================================
		ELEMENTS DRAG 'N' DROP SCRIPTS
==========================================
==========================================
*/		
        private function Me_OnDragEnter(evt:DragEvent):void{
        	try{
        		if (evt.dragSource.hasFormat("TreeObject")){
                	DragManager.acceptDragDrop(this);
            	}
        	}catch(err:Error){
        		Logger.LogE(err);
        	}
        }
        
        private function Me_OnDragDrop(evt:DragEvent):void{
        	try{
        		if (evt.dragSource.hasFormat("TreeObject")){
                	var itemXML:XML = evt.dragSource.dataForFormat("TreeObject") as XML;
                	
                	if(itemXML.@enabled == "true") {
	                	var added_node:Node = this.nodes.AddNode(itemXML.@name,itemXML.@ThumbnailID,itemXML);
	                	added_node.x = this.mouseX;
	                	added_node.y = this.mouseY;
	                	itemXML.@enabled="false";	
                	}
            	}
        	}catch(err:Error){
        		Logger.LogE(err);
        	}
        }
        
/*
==========================================
==========================================
		ELEMENTS DRAG 'N' DROP SCRIPTS
==========================================
==========================================
*/

		private function DelayedCall_AddSelectionIntoGroup(grp:GroupItem):void{
			try{
				for each ( var singleObj:UIComponent in SelectionManager.SelectedItems ){
					var pt:Point = new Point(singleObj.x,singleObj.y);
					
					pt = this.nodes.localToGlobal(pt);
					singleObj.parent.removeChild(singleObj);
					pt = grp.nodes.globalToContent(pt);
					
					singleObj.x = pt.x;
					singleObj.y = pt.y;
					grp.nodes.addChild(singleObj);
				}
			}catch(err:Error){
				Logger.LogE(err);
			}
		}
		
		public function AddGroup(rect:Rectangle):void{
			try{
				var grp:GroupItem = new GroupItem();
				grp.SetBG(0x0099FF, 0.2);
				grp.width = rect.width ;
				grp.height = rect.height + 40;
				grp.x = rect.x;
				grp.y = rect.y - 40;
				this.nodes.addChild(grp);
				setTimeout(this.DelayedCall_AddSelectionIntoGroup,100,grp);

			}catch(err:Error){
				throw err;
			}
		}
				
		public function DeleteGroup(grpItem:GroupItem):void{
			try{
				while ( grpItem.nodes.numChildren > 0 ){
					var singleObj:UIComponent = UIComponent(grpItem.nodes.getChildAt(0));
					if ( singleObj is Node ){
						Node(singleObj).data.@enabled = "true";
					}
					grpItem.nodes.removeChild(singleObj);
				}
				this.nodes.removeChild(grpItem);
			}catch(err:Error){
				throw err;
			}
		}
				
		public function UnGroup(grpItem:GroupItem):void{
			try{
				while ( grpItem.nodes.numChildren > 0 ){
					var singleObj:UIComponent = UIComponent(grpItem.nodes.getChildAt(0));
					var pt:Point = new Point(singleObj.x,singleObj.y);
					
					pt = grpItem.nodes.localToGlobal(pt);
					
					grpItem.nodes.removeChild(singleObj);
					
					pt = this.nodes.globalToContent(pt);
					
					singleObj.x = pt.x;
					singleObj.y = pt.y;
					this.nodes.addChild(singleObj);
				}
				this.nodes.removeChild(grpItem);
			}catch(err:Error){
				throw err;
			}
		}		
	}
}